﻿using EightOData.Extensions.Layout;
using EightOData.Extensions.WebServices;
using EightOData.Model;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Navigation;

namespace EightOData
{
    /// <summary>
    /// This page displays search results when a global search is directed to this application.
    /// </summary>
    public sealed partial class SearchResultsPage : INotifyPropertyChanged
    {
        #region Properties

        // Résultats de recherche
        public ObservableCollection<GroupInfoList<Gift>> Results { get; private set; }
        public List<Filter> Filters { get; private set; }

        // Mots-clés de recherche
        private String _queryText;
        public String QueryText
        {
            get { return _queryText; }
            set
            {
                _queryText = value;
                RaisePropertyChanged("QueryTextVisibility");
            }
        }

        // On affiche le message si le texte n'est pas vide, sinon, on le cache
        public Visibility QueryTextVisibility
        {
            get { return String.IsNullOrWhiteSpace(QueryText) ? Visibility.Collapsed : Visibility.Visible; }
        }

        #endregion

        #region Constructor

        /// <summary>
        /// Constructeur. Initialise les composants graphiques ainsi que les collections.
        /// </summary>
        public SearchResultsPage()
        {
            InitializeComponent();
            Results = new ObservableCollection<GroupInfoList<Gift>>();
            Filters = new List<Filter>();
        }

        #endregion

        #region Methods

        /// <summary>
        /// Initialise les données de la page et récupère les résultats de recherche selon les entrées utilisateur.
        /// </summary>
        /// <param name="keyword">Mot-clé entré par l'utilisateur</param>
        private async void Initialize(String keyword)
        {
            // Aucune recherche si aucun mot-clé n'a été rentré
            if (String.IsNullOrWhiteSpace(keyword))
                return;

            QueryText = "\"" + keyword + "\"";

            // Récupération asynchrone des données du service d'eBay sous forme de document XML (XDocument)
            var results = await EbayHelper.FindItemsByKeywords(keyword);

            // Traitement du document XML
            // TODO : A revoir
            var groups = results
                // Récupération des objets
                .Descendants(EbayHelper.Namespace + "item")
                // Récupération des 20 premiers objets
                .Take(20)
                // Pour chaque objet récupéré, on crée un objet de type Gift
                .Select(x => new Gift
                {
                    Name = x.Element(EbayHelper.Namespace + "title") != null ? x.Element(EbayHelper.Namespace + "title").Value : String.Empty,
                    Description = x.Element(EbayHelper.Namespace + "subtitle") != null ? x.Element(EbayHelper.Namespace + "subtitle").Value : String.Empty,
                    Image = x.Element(EbayHelper.Namespace + "galleryURL") != null ? new Uri(x.Element(EbayHelper.Namespace + "galleryURL").Value) : null,
                })
                // Répartition des cadeaux par groupe selon la première lettre du nom
                .GroupBy(x => x.Name[0])
                .OrderBy(x => x.Key)
                .Select(x => new { GroupName = x.Key, Items = x });

            // Sélection des cadeaux par groupe
            foreach (var group in groups)
            {
                var info = new GroupInfoList<Gift> { Key = group.GroupName };

                foreach (var item in group.Items)
                    info.Add(item);

                Results.Add(info);
            }

            this.DataContext = this;
            (SemanticZoom.ZoomedOutView as ListViewBase).ItemsSource = DataSource.View.CollectionGroups;
        }

        #endregion

        #region Events

        /// <summary>
        /// Invoked when this page is about to be displayed in a Frame.
        /// </summary>
        /// <param name="e">Event data that describes how this page was reached.  The Parameter
        /// property is typically used to configure the page.</param>
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            if (e.Parameter != null)
                Initialize(e.Parameter.ToString());
        }

        /// <summary>
        /// Invoked when a filter is selected using the ComboBox in snapped view state.
        /// </summary>
        /// <param name="sender">The ComboBox instance.</param>
        /// <param name="e">Event data describing how the selected filter was changed.</param>
        void Filter_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            // Determine what filter was selected
            var selectedFilter = e.AddedItems.FirstOrDefault() as Filter;

            if (selectedFilter != null)
            {
                // Mirror the results into the corresponding Filter object to allow the
                // RadioButton representation used when not snapped to reflect the change
                selectedFilter.Active = true;

                // TODO: Respond to the change in active filter by setting this.DefaultViewModel["Results"]
                //       to a collection of items with bindable Image, Title, Subtitle, and Description properties
            }

            // Display informational text when there are no search results.
            VisualStateManager.GoToState(this, "NoResultsFound", true);
        }

        /// <summary>
        /// Invoked when a filter is selected using a RadioButton when not snapped.
        /// </summary>
        /// <param name="sender">The selected RadioButton instance.</param>
        /// <param name="e">Event data describing how the RadioButton was selected.</param>
        void Filter_Checked(object sender, RoutedEventArgs e)
        {
            // Mirror the change into the CollectionViewSource used by the corresponding ComboBox
            // to ensure that the change is reflected when snapped
            if (FilterSource.View != null)
            {
                var filter = (sender as FrameworkElement).DataContext;
                FilterSource.View.MoveCurrentTo(filter);
            }
        }

        /// <summary>
        /// Effectue la navigation vers la page précédente.
        /// </summary>
        private void BackButton_Tapped(object sender, TappedRoutedEventArgs e)
        {
            Frame.Navigate(typeof(WishListPage));
        }

        #region INotifyPropertyChanged Implementation

        public event PropertyChangedEventHandler PropertyChanged;

        public void RaisePropertyChanged(String propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion

        #endregion
    }
}
